home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / grafica / amhelios / prog_rad.cpp < prev    next >
C/C++ Source or Header  |  1999-01-01  |  11KB  |  394 lines

  1. ////////////////////////////////////////////////////////////
  2. //
  3. //  PROG_RAD.CPP - Progressive Refinement Radiosity Class
  4. //
  5. //  Version:    1.03A
  6. //
  7. //  History:    94/08/23 - Version 1.00A release.
  8. //              94/09/24 - Modified Open function.
  9. //              94/11/26 - Added Interpolate function.
  10. //                       - Modified Close, Calculate,
  11. //                         AddAmbient and CalcOverShoot
  12. //                         functions.
  13. //              94/12/16 - Version 1.01A release.
  14. //              95/02/05 - Version 1.02A release.
  15. //              95/07/16 - Removed ambient exitance addition
  16. //                         from Calculate function.
  17. //                       - Added ambient exitance addition
  18. //                         to Close function.
  19. //              95/07/21 - Version 1.02B release.
  20. //              96/02/14 - Version 1.02C release.
  21. //              96/04/01 - Version 1.03A release.
  22. //
  23. //  Compilers:  Microsoft Visual C/C++ Professional V1.5
  24. //              Borland C++ Version 4.5
  25. //
  26. //  Author:     Ian Ashdown, P.Eng.
  27. //              byHeart Software Limited
  28. //              620 Ballantree Road
  29. //              West Vancouver, B.C.
  30. //              Canada V7S 1W3
  31. //              Tel. (604) 922-6148
  32. //              Fax. (604) 987-7621
  33. //
  34. //  Copyright 1994-1996 byHeart Software Limited
  35. //
  36. //  The following source code has been derived from:
  37. //
  38. //    Ashdown, I. 1994. Radiosity: A Programmer's
  39. //    Perspective. New York, NY: John Wiley & Sons.
  40. //
  41. //  It may be freely copied, redistributed, and/or modified
  42. //  for personal use ONLY, as long as the copyright notice
  43. //  is included with all source code files.
  44. //
  45. ////////////////////////////////////////////////////////////
  46.  
  47. #include "prog_rad.h"
  48.  
  49. // Open progressive radiosity renderer
  50. BOOL ProgRad::Open( Environ *pe )
  51. {
  52.   penv = pe;            // Save environment pointer
  53.   step_count = 0;       // Reset step count
  54.   convergence = 1.0;    // Convergence
  55.   start = clock();      // Initialize start time
  56.   InitExitance();       // Initialize exitances
  57.  
  58.   if (amb_flag == TRUE) // Ambient exitance required ?
  59.   {
  60.     CalcInterReflect(); // Calculate interreflection factor
  61.     CalcAmbient();      // Calculate initial ambient term
  62.   }
  63.  
  64.   // Allocate form factor array
  65.   if ((ff_array = new float[penv->GetNumElem()]) == NULL)
  66.     return FALSE;
  67.  
  68.   return TRUE;
  69. }
  70.  
  71. // Close progressive radiosity renderer
  72. void ProgRad::Close()
  73. {
  74.   // Release form factor array
  75.   if (ff_array != NULL)
  76.   {
  77.     delete [] ff_array;
  78.     ff_array = NULL;
  79.   }
  80.  
  81.   if (penv != NULL)
  82.   {
  83. //    if (amb_flag == TRUE)
  84. //    {
  85. //      AddAmbient();     // Add ambient exitance
  86. //    }
  87.  
  88.     Interpolate();      // Interpolate vertex exitances
  89.     AddEmittance();     // Add parent surface emittances
  90.   }
  91. }
  92.  
  93. // Snapshot current radiosity render state
  94. void ProgRad::Snapshot()
  95. {
  96.   if (penv != NULL)
  97.   {
  98. //    if (amb_flag == TRUE)
  99. //    {
  100. //      AddAmbient();     // Add ambient exitance
  101. //    }
  102.  
  103.     Interpolate();      // Interpolate vertex exitances
  104.     AddEmittance();     // Add parent surface emittances
  105.   }
  106. }
  107.  
  108. // Calculate element exitances
  109. BOOL ProgRad::Calculate()
  110. {
  111.   float rff;            // Reciprocal form factor
  112.   BOOL self;            // Self patch flag
  113.   WORD ff_index = 0;    // Form factor array index
  114.   Element3 *pelem;      // Element pointer
  115.   Instance *pinst;      // Instance pointer
  116.   Patch3 *ppatch;       // Patch pointer
  117.   Surface3 *psurf;      // Surface pointer
  118.   Spectra delta;        // Delta exitance
  119.   Spectra reflect;      // Surface reflectance
  120.   Spectra shoot;        // Shoot exitance
  121.  
  122.   // Check for maximum number of steps
  123.   if (step_count >= max_step)
  124.     return TRUE;
  125.  
  126.   UpdateUnsentStats();  // Update unsent flux statistics
  127.  
  128.   // Check for convergence
  129.   if (convergence < stop_criterion)
  130.     return TRUE;
  131.  
  132.   // Calculate form factors
  133.   ffd.CalcFormFactors(pmax, penv->GetInstPtr(), ff_array,
  134.       penv->GetNumElem());
  135.  
  136.   if (over_flag == TRUE)
  137.   {
  138.     CalcOverShoot();    // Calculate overshooting parameters
  139.   }
  140.  
  141.   // Walk the instance list
  142.   pinst = penv->GetInstPtr();
  143.   while (pinst != NULL)
  144.   {
  145.     // Walk the surface list
  146.     psurf = pinst->GetSurfPtr();
  147.     while (psurf != NULL)
  148.     {
  149.       // Get surface reflectance
  150.       reflect = psurf->GetReflectance();
  151.  
  152.  
  153.       // Walk the patch list
  154.       ppatch = psurf->GetPatchPtr();
  155.       while (ppatch != NULL)
  156.       {
  157.         // Check for self patch
  158.         self = (BOOL)((ppatch == pmax) ? TRUE : FALSE);
  159.  
  160.         // Walk the element list
  161.         pelem = ppatch->GetElementPtr();
  162.         while (pelem != NULL)
  163.         {
  164.           if (self == FALSE)    // Ignore self
  165.           {
  166.             // Check element visibility
  167.             if (ff_array[ff_index] > 0.0)
  168.             {
  169.               // Compute reciprocal form factor
  170.               rff = (float) min((double) ff_array[ff_index]
  171.                   * pmax->GetArea() / pelem->GetArea(),
  172.                   1.0);
  173.  
  174.               // Get shooting patch unsent exitance
  175.               shoot = pmax->GetExitance();
  176.  
  177.               if (over_flag == TRUE)
  178.               {
  179.                 // Add overshoot exitance
  180.                 shoot.Add(overshoot);
  181.               }
  182.  
  183.               // Calculate delta exitance
  184.               delta = Mult(reflect, shoot);
  185.               delta.Scale(rff);
  186.  
  187.               // Update element exitance
  188.               pelem->GetExitance().Add(delta);
  189.  
  190.               // Update patch unsent exitance
  191.               delta.Scale(pelem->GetArea() /
  192.                   ppatch->GetArea());
  193.               ppatch->GetExitance().Add(delta);
  194.             }
  195.           }
  196.           pelem = pelem->GetNext();
  197.           ff_index++;
  198.         }
  199.         ppatch = ppatch->GetNext();
  200.       }
  201.       psurf = psurf->GetNext();
  202.     }
  203.     pinst = pinst->GetNext();
  204.   }
  205.  
  206.   if (over_flag == TRUE)
  207.   {
  208.     // Subtract shot exitance from patch unsent exitance
  209.     pmax->GetExitance().Subtract(shoot);
  210.   }
  211.   else
  212.   {
  213.     // Reset unsent exitance to zero
  214.     pmax->GetExitance().Reset();
  215.   }
  216.  
  217.   if (amb_flag == TRUE)
  218.   {
  219.     CalcAmbient();      // Recalculate ambient exitance
  220.   }
  221.  
  222.   step_count++;         // Increment step count
  223.   return FALSE;         // Convergence not achieved yet
  224. }
  225.  
  226. // Interpolate vertex reflected exitances
  227. void ProgRad::Interpolate()
  228. {
  229.   int num_elem;         // Number of elements
  230.   Element3 *pelem;      // Element pointer
  231.   ElemList *pel;        // Element list pointer
  232.   Instance *pinst;      // Instance pointer
  233.   Vertex3 *pvert;       // Vertex pointer
  234.   Spectra exitance;     // Vertex exitance
  235.   Spectra reflect;      // Surface reflectance
  236.   Spectra delta_amb;    // Delta ambient exitance
  237.  
  238.   // Walk the instance list
  239.   pinst = penv->GetInstPtr();
  240.   while (pinst != NULL)
  241.   {
  242.     // Walk the vertex list
  243.     pvert = pinst->GetVertPtr();
  244.     while (pvert != NULL)
  245.     {
  246.       // Initialize vertex reflected exitance
  247.       pvert->GetExitance().Reset();
  248.  
  249.       // Walk the element list
  250.       pel = pvert->GetElemListPtr();
  251.       num_elem = 0;
  252.       while (pel != NULL)
  253.       {
  254.         // Get the element pointer
  255.         pelem = pel->GetElemPtr();
  256.  
  257.         exitance = pelem->GetExitance();
  258.         reflect = pelem->GetParentPtr()->GetParentPtr()->GetReflectance();
  259.  
  260.         if(amb_flag == TRUE)
  261.         {
  262.           delta_amb = Mult(ambient, reflect);
  263.           exitance.Add(delta_amb);
  264.         }
  265.  
  266.         // Add element reflected exitance
  267.         pvert->GetExitance().Add(exitance);
  268.  
  269.         pel = pel->GetNext();
  270.         num_elem++;
  271.       }
  272.  
  273.       // Scale vertex reflected exitance according to number
  274.       // of shared elements
  275.       pvert->GetExitance().Scale(1.0 / (double) num_elem);
  276.  
  277.       pvert = pvert->GetNext();
  278.     }
  279.     pinst = pinst->GetNext();
  280.   }
  281. }
  282.  
  283. void ProgRad::AddAmbient()      // Add ambient exitance
  284. {
  285.   Element3 *pelem;      // Element pointer
  286.   Instance *pinst;      // Instance pointer
  287.   Patch3 *ppatch;       // Patch pointer
  288.   Spectra delta_amb;    // Delta ambient exitance
  289.   Spectra reflect;      // Surface reflectance
  290.   Surface3 *psurf;      // Surface pointer
  291.  
  292.   // Walk the instance list
  293.   pinst = penv->GetInstPtr();
  294.   while (pinst != NULL)
  295.   {
  296.     // Walk the surface list
  297.     psurf = pinst->GetSurfPtr();
  298.     while (psurf != NULL)
  299.     {
  300.       // Get surface reflectance
  301.       reflect = psurf->GetReflectance();
  302.  
  303.       // Walk the patch list
  304.       ppatch = psurf->GetPatchPtr();
  305.       while (ppatch != NULL)
  306.       {
  307.         // Walk the element list
  308.         pelem = ppatch->GetElementPtr();
  309.         while (pelem != NULL)
  310.         {
  311.           // Calculate delta ambient exitance
  312.           delta_amb = Mult(ambient, reflect);
  313.  
  314.           // Update element exitance
  315.           pelem->GetExitance().Add(delta_amb);
  316.  
  317.           pelem = pelem->GetNext();
  318.         }
  319.         ppatch = ppatch->GetNext();
  320.       }
  321.       psurf = psurf->GetNext();
  322.     }
  323.     pinst = pinst->GetNext();
  324.   }
  325. }
  326.  
  327. // Calculate overshooting parameters
  328. void ProgRad::CalcOverShoot()
  329. {
  330.   BOOL self;            // Self patch flag
  331.   WORD ff_index = 0;    // Form factor array index
  332.   Element3 *pelem;      // Element pointer
  333.   Instance *pinst;      // Instance pointer
  334.   Patch3 *ppatch;       // Patch pointer
  335.   Spectra spr;          // Shooting patch reflectance
  336.   Spectra unsent;       // Patch unsent exitance
  337.   Surface3 *psurf;      // Surface pointer
  338.  
  339.   overshoot.Reset();    // Reset overshooting parameters
  340.  
  341.   // Walk the instance list
  342.   pinst = penv->GetInstPtr();
  343.   while (pinst != NULL)
  344.   {
  345.     // Walk the surface list
  346.     psurf = pinst->GetSurfPtr();
  347.     while (psurf != NULL)
  348.     {
  349.       // Walk the patch list
  350.       ppatch = psurf->GetPatchPtr();
  351.       while (ppatch != NULL)
  352.       {
  353.         // Check for self patch
  354.         self = (BOOL)((ppatch == pmax) ? TRUE : FALSE);
  355.  
  356.         // Walk the element list
  357.         pelem = ppatch->GetElementPtr();
  358.         while (pelem != NULL)
  359.         {
  360.           if (self == FALSE)    // Ignore self
  361.           {
  362.             // Get unsent patch exitance
  363.             unsent = ppatch->GetExitance();
  364.  
  365.             // Limit unsent exitance to positive color band
  366.             // values
  367.             unsent.Limit();
  368.  
  369.             // Multiply unsent exitance by patch-to-
  370.             // element form factor
  371.             unsent.Scale(ff_array[ff_index]);
  372.  
  373.             // Update overshooting parameters
  374.             overshoot.Add(unsent);
  375.           }
  376.           pelem = pelem->GetNext();
  377.           ff_index++;
  378.         }
  379.         ppatch = ppatch->GetNext();
  380.       }
  381.       psurf = psurf->GetNext();
  382.     }
  383.     pinst = pinst->GetNext();
  384.   }
  385.  
  386.   // Get shooting patch reflectance
  387.   spr = pmax->GetParentPtr()->GetReflectance();
  388.  
  389.   // Multiply overshooting parameters by shooting patch
  390.   // reflectance
  391.   overshoot.Mult(spr);
  392. }
  393.  
  394.